﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate.Criterion;

namespace WorkOrders.Data
{
    public class Repository<T> : IRepository<T> where T : class
    {
        static Repository()
        {
        }

        protected ISession Session
        {
            get
            {
                return SessionManager.GetSession<T>();
            }
        }

        public void CloseSession()
        {
            SessionManager.CloseSession();
        }

        public T Find(int id)
        {
            return Session.Get<T>(id);
        }

        public virtual IList<T> FindAll()
        {
            return FindAll((string[])null);
        }

        public virtual IList<T> FindAll(string orderBy)
        {
            return FindAll(new string[] {orderBy});
        }

        public virtual IList<T> FindAll(string[] orderBy)
        {
            var criteria = Session.CreateCriteria(typeof(T));
            if (orderBy != null)
            {
                foreach (var field in orderBy)
                {
                    if (!String.IsNullOrEmpty(field))
                    {
                        criteria.AddOrder(Order.Asc(field));
                    }
                }
            }
            return criteria.List<T>();
        }

        public void SaveOrUpdate(T entity)
        {
            try
            {
                ITransaction tx = Session.BeginTransaction();
                try
                {
                    Session.SaveOrUpdate(entity);
                    tx.Commit();
                }
                catch (HibernateException)
                {
                    tx.Rollback();
                    throw;
                }
            }
            finally
            {
                CloseSession();
            }
        }

        public void Delete(T entity)
        {
            try
            {
                ITransaction tx = Session.BeginTransaction();
                try
                {
                    Session.Delete(entity);
                    tx.Commit();
                }
                catch (HibernateException)
                {
                    tx.Rollback();
                }
            }
            finally
            {
                CloseSession();
            }
        }

        public int Count()
        {
            var criteria = Session.CreateCriteria(typeof(T))
                .SetProjection(Projections.RowCount());
            return criteria.UniqueResult<int>();
        }
    }
}